package engine.render;

import engine.Displays;
import math.Maths;
import math.vector.Vecmath;
import math.vector.vec3f;

public class Frustum 
{
    
    private float zNear;
    private float zFar;
    private float zRatio;
    private float yTop;
    private float xRight;
    
    public vec3f[] normals;
    public vec3f[] planePts;
    
    private vec3f posCamera;
    public vec3f getPosCamera() 
    {
        return posCamera;
    }
    
    private vec3f dirCamera;
    public vec3f getDirCamera() 
    {
        return dirCamera;
    }
    
    private vec3f dirCamRight;
    private vec3f dirCamUp;
    
    public Frustum(Displays display, float znear, float zfar) 
    {
        zNear = znear;
        zFar = zfar;
        zRatio = zFar / zNear;
        yTop = Maths.tanDeg(display.fov() * 0.5f) * zNear;
        xRight = yTop * display.aspectRatio();
        normals = new vec3f[6];
        planePts = new vec3f[6];
        posCamera = new vec3f();
        dirCamera = new vec3f();
    }
    
    public void updateMinimal(GLManager glManager) 
    {
        posCamera = glManager.getTranslation().getInverted();
        dirCamera = glManager.getCamDir();
    }
    
    public void recalculate(GLManager glManager) 
    {
        dirCamRight = glManager.getCamDirRight();
        dirCamUp = glManager.getCamDirUp();
        
        vec3f nDir = Vecmath.scalarMult(zNear, dirCamera);
        vec3f fDir = Vecmath.scalarMult(zFar, dirCamera);
        vec3f rnDir = Vecmath.scalarMult(xRight, dirCamRight);
        vec3f lnDir = Vecmath.getInverted(rnDir);
        vec3f rfDir = Vecmath.scalarMult(xRight * zRatio, dirCamRight);
        vec3f lfDir = Vecmath.getInverted(rfDir);
        vec3f tnDir = Vecmath.scalarMult(yTop, dirCamUp);
        vec3f bnDir = Vecmath.getInverted(tnDir);
        vec3f tfDir = Vecmath.scalarMult(yTop * zRatio, dirCamUp);
        vec3f bfDir = Vecmath.getInverted(tfDir);

        vec3f n = Vecmath.add(posCamera, nDir);
        vec3f f = Vecmath.add(posCamera, fDir);
        
        vec3f nt = Vecmath.add(n, tnDir);
        vec3f nb = Vecmath.add(n, bnDir);
        vec3f ft = Vecmath.add(f, tfDir);
        vec3f fb = Vecmath.add(f, bfDir);
        
        vec3f nlt = Vecmath.add(nt, lnDir);
        vec3f nlb = Vecmath.add(nb, lnDir);
        vec3f nrt = Vecmath.add(nt, rnDir);
        vec3f nrb = Vecmath.add(nb, rnDir);
        
        vec3f flt = Vecmath.add(ft, lfDir);
        vec3f flb = Vecmath.add(fb, lfDir);
        vec3f frt = Vecmath.add(ft, rfDir);
//        vec3f frb = Vecmath.add(fb, rfDir);
        
        vec3f nNorm = Vecmath.getSurfaceNormal(nlb, nlt, nrt);
        vec3f fNorm = Vecmath.getSurfaceNormal(flt, flb, frt);
        vec3f lNorm = Vecmath.getSurfaceNormal(nlt, nlb, flt);
        vec3f rNorm = Vecmath.getSurfaceNormal(nrb, nrt, frt);
        vec3f bNorm = Vecmath.getSurfaceNormal(nlb, nrb, flb);
        vec3f tNorm = Vecmath.getSurfaceNormal(nrt, nlt, frt);

        normals[0] = nNorm;
        normals[1] = fNorm;
        normals[2] = lNorm;
        normals[3] = rNorm;
        normals[4] = bNorm;
        normals[5] = tNorm;

        planePts[0] = nlt;
        planePts[1] = flt;
        planePts[2] = nlt;
        planePts[3] = nrt;
        planePts[4] = nlb;
        planePts[5] = nlt;
    }
    
}
